package com.origin.netlibrary

import android.app.Application
import android.text.TextUtils
import android.util.Log
import com.origin.netlibrary.listener.Response
import com.origin.netlibrary.netapi.DownloadService
import com.origin.netlibrary.netapi.RequestFormat
import com.origin.utils.gson.GsonUtils
import kotlinx.coroutines.*
import retrofit2.Call
import java.io.IOException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

object NetUtils {

    private var bodyJsonSyntaxException =
        "{\"code\":201,\"data\":null,\"msg\":\"类型异常\"}"
    private var bodyEmpty = "{\"code\":204,\"data\":null,\"msg\":\"bodyEmpty\"}"

    public fun setBodyJsonSyntaxException(exStr: String) {
        bodyJsonSyntaxException = exStr;
    }

    public fun setBodyEmpty(exStr: String) {
        bodyEmpty = exStr;
    }


    private lateinit var application: Application
    public fun getApplication(): Application {
        return application
    }

    fun getInstance(application: Application) {
        this.application = application
    }

    private val retrofitManager: RetrofitManager by lazy {
        RetrofitManager.getInstance(
            application
        )
    }
    val restService: RequestFormat by lazy {
        retrofitManager.requestFormat
    }
    val downloadService: DownloadService by lazy {
        retrofitManager.downloadService
    }

    fun asyn(viewModelScope: CoroutineScope, ioFunction: (() -> Unit), mainFunction: (() -> Unit)) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                ioFunction.invoke()
            }
            mainFunction.invoke()
        }
    }

    inline fun <reified T> getType(value: T) {
        println("$value 的类型是 ${T::class.java}")
    }

    //  implementation 'com.github.ikidou:TypeBuilder:1.0'
    suspend fun <T> Call<String>.getSuperNet(
        viewModelScope: CoroutineScope,
        type: Type
    ): T {
        val self = this;
        return viewModelScope.let {
            NetStack.saveVmMapCall(viewModelScope, self)
            val response = self.requestNet()
            var responseBody = response.body();

            Log.e("getSuperNet====>返回数据为空 A  response.code",   response.code().toString())
            if (response.isSuccessful){
                Log.e("getSuperNet====>返回数据为空 A", TextUtils.isEmpty(responseBody).toString())
            }else{

                Log.e("getSuperNet====>返回数据为空 B", TextUtils.isEmpty(responseBody).toString())


                val errorBody = response.errorBody()
                // 如果你知道错误体的结构，可以进一步解析它
                if (errorBody != null) {
                    try {
                        val errorJson = errorBody.string()

                        Log.e("getSuperNet====>返回数据为空 C", "Error: ${errorJson} Server responded with status code: ${response.code()}" )
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                } else {
                    // 没有错误体的情况下，只能根据状态码给出一般性提示
                    Log.e("getSuperNet====>返回数据为空 D", "Server responded with status code: ${response.code()}")
                }
            }


            if (TextUtils.isEmpty(responseBody)) {
                responseBody = bodyEmpty;
            }

            try {
                GsonUtils.gson.fromJson<T>(responseBody, type)
            } catch (e: Exception) {
                GsonUtils.gson.fromJson<T>(
                    String.format(bodyJsonSyntaxException, e.toString()),
                    type
                )
            }

        }
    }


    suspend fun <T> Call<String>.getNet(
        viewModelScope: CoroutineScope,
        responseListener: Response<T>
    ): T {
        val self = this;
        return viewModelScope.let {
            NetStack.saveVmMapCall(viewModelScope, self)
            val response = self.requestNet()
            var responseBody = response.body();
            if (TextUtils.isEmpty(responseBody)) {
                responseBody = bodyEmpty;
            }


            val type1: Type = (responseListener.javaClass.getGenericSuperclass() as ParameterizedType).getActualTypeArguments().get(0)
            println("type1==> ${type1}")
            println("type2==> ${responseBody}")

            if (type1.toString() == "class java.lang.String") {
                return (responseBody ?: "") as T
            }

            val type = responseListener.getType()
            try {
                GsonUtils.gson.fromJson<T>(responseBody, type)
            } catch (e: Exception) {
                GsonUtils.gson.fromJson<T>(
                    String.format(bodyJsonSyntaxException, e.toString()),
                    type
                )
            }

        }
    }

    suspend fun <T> Call<String>.getNetCancel(
        responseListener: Response<T>
    ): T {
        val self = this;
        return withContext(Dispatchers.IO) {
            val response = self.requestNet()
            var responseBody = response.body();
            if (TextUtils.isEmpty(responseBody)) {
                responseBody = bodyEmpty;
            }
            val type = responseListener.getType()
            try {
                GsonUtils.gson.fromJson<T>(responseBody, type)
            } catch (e: Exception) {
                GsonUtils.gson.fromJson<T>(
                    String.format(bodyJsonSyntaxException, e.toString()),
                    type
                )
            }

        }
    }


}